#lang racket

(require rackunit)
(require rackunit/text-ui)
(require 2htdp/image)
(require "tetra-tipos.rkt")
(require "base.rkt")
(require "tetris.rkt")

;; Constantes usadas nos testes
(define TIMEOUT 14)

(define TT1 (tetramino T_TIPOS 1 (posn 1 0) T_COR))
(define TT1_POS (list (posn 1 1)
                      (posn 2 1) (posn 2 2)
                      (posn 3 1)))
(define TT1_CENTRA_10 (tetramino T_TIPOS 1 (posn 1 3) T_COR))

(define TZ2 (tetramino Z_TIPOS 2 (posn 2 3) Z_COR))
(define TZ2_POS (list (posn 3 3) (posn 3 4)
                      (posn 4 4) (posn 4 5)))
(define TZ2_CENTRA_15 (tetramino Z_TIPOS 2 (posn 2 6) Z_COR))

(define TI0 (tetramino I_TIPOS 0 (posn -1 1) I_COR))
(define TI0_POS (list (posn 0 1) (posn 0 2) (posn 0 3) (posn 0 4)))
(define TI0_CENTRA_12 (tetramino I_TIPOS 0 (posn -1 4) I_COR))

(define C1 (list (list 0 0 0 0 0 0 0)   ; 0
                 (list 0 0 0 0 0 0 0)   ; 1
                 (list 6 0 0 0 0 0 0)   ; 2
                 (list 4 0 2 4 6 1 1)   ; 3
                 (list 3 4 0 0 0 0 0)   ; 4
                 (list 1 2 4 3 2 5 6))) ; 5
                 ;     0 1 2 3 4 5 6

(define C1_LARGURA 7)
(define C1_ALTURA 6)
;; algumas posições ocupadas em C1
(define C1_OCUPADAS (list (posn 2 0) (posn 3 2) (posn 4 1)))
;; algumas posições livres em C1
(define C1_LIVRES (list (posn 0 0) (posn 3 1) (posn 4 2)))

(define C T_COR)

; Representa C1 com o tetraminó TT1 fixado no campo
(define C1_FIXA_TT1 (list (list 0 0 0 0 0 0 0)   ; 0
                          (list 0 C 0 0 0 0 0)   ; 1
                          (list 6 C C 0 0 0 0)   ; 2
                          (list 4 C 2 4 6 1 1)   ; 3
                          (list 3 4 0 0 0 0 0)   ; 4
                          (list 1 2 4 3 2 5 6))) ; 5
                          ;     0 1 2 3 4 5 6

; Representa C1_FIXA_TT1 sem as linha completas
(define C1_FIXA_TT1_LIMPA (list (list 0 0 0 0 0 0 0)   ; 0
                                (list 0 0 0 0 0 0 0)   ; 1
                                (list 0 0 0 0 0 0 0)   ; 2
                                (list 0 C 0 0 0 0 0)   ; 3
                                (list 6 C C 0 0 0 0)   ; 4
                                (list 3 4 0 0 0 0 0))) ; 5
                                ;     0 1 2 3 4 5 6

(define C2 (list (list 0 0 0 0 0)
                 (list 0 0 0 0 0)
                 (list 0 0 0 0 0)
                 (list 0 0 0 0 0)
                 (list 0 0 0 0 0)
                 (list 0 0 0 0 0)
                 (list 0 0 0 0 0)))

(define C2_LARGURA 5)
(define C2_ALTURA 7)

(define make-linha-tests
  (test-suite
   "make-linha tests"
   (check-equal? (make-linha 0) empty)
   (check-equal? (make-linha 5) (list 0 0 0 0 0))))

(define make-campo-tests
  (test-suite
   "make-campo tests"
   (check-equal? (make-campo C2_LARGURA C2_ALTURA) C2)))

(define centraliza-tests
  (test-suite
   "centraliza tests"
   (check-equal? (centraliza TT1 10)
                 TT1_CENTRA_10)
   (check-equal? (centraliza TZ2 15)
                 TZ2_CENTRA_15)
   (check-equal? (centraliza TI0 12)
                 TI0_CENTRA_12)))

(define make-tetris-tests
  (test-suite
   "make-tetris tests"
   (check-equal? (make-tetris C2_LARGURA C2_ALTURA (list TT1 TZ2 TI0) TIMEOUT)
                 (tetris C2
                         C2_LARGURA
                         C2_ALTURA
                         (centraliza TT1 C2_LARGURA)
                         (list TZ2 TI0)
                         TIMEOUT))))

(define tetramino->pos-tests
  (test-suite
   "tetramino->pos tests"
   (check-equal? (tetramino->lista-pos TT1) TT1_POS)
   (check-equal? (tetramino->lista-pos TZ2) TZ2_POS)
   (check-equal? (tetramino->lista-pos TI0) TI0_POS)
   ;; testes para verificar a list(posn) do tetramino I, pois o I0 é o unico que a peça começa na segunda linha do campo
   (check-equal? (tetramino->lista-pos (tetramino I_TIPOS 0 (posn 1 0) I_COR))                                                                                                              (list (posn 2 0) (posn 2 1) (posn 2 2) (posn 2 3)))
   (check-equal? (tetramino->lista-pos (tetramino I_TIPOS 0 (posn 0 0) I_COR))                                                                                                              (list (posn 1 0) (posn 1 1) (posn 1 2) (posn 1 3)))
   (check-equal? (tetramino->lista-pos (tetramino I_TIPOS 0 (posn 1 2) I_COR))                                                                                                              (list (posn 2 2) (posn 2 3) (posn 2 4) (posn 2 5)))
   (check-equal? (tetramino->lista-pos (tetramino I_TIPOS 1 (posn 1 0) I_COR))                                                                                                              (list (posn 1 1) (posn 2 1) (posn 3 1) (posn 4 1)))))

(define lop-validas?-tests
  (test-suite
   "lop-validas? tests"
   (check-equal? (lop-validas? empty 5 8)
                 #t)
   ;; testa os extremos
   (check-equal? (lop-validas? (list (posn 0 0)
                                     (posn (sub1 C1_ALTURA) 0)
                                     (posn 0 (sub1 C1_LARGURA))
                                     (posn (sub1 C1_ALTURA) (sub1 C1_LARGURA)))
                               C1_LARGURA
                               C1_ALTURA)
                 #t)
   (check-equal? (lop-validas? (list (posn 0 0)
                                     (posn C1_ALTURA 0) ; linha inválida
                                     (posn 1 2))
                               C1_LARGURA
                               C1_ALTURA)
                 #f)
   (check-equal? (lop-validas? (list (posn  2 3)
                                     (posn -1 3)) ; linha inválida
                               C1_LARGURA
                               C1_ALTURA)
                 #f)
   (check-equal? (lop-validas? (list (posn 0 0)
                                     (posn 0 C1_LARGURA) ; coluna inválida
                                     (posn 1 2))
                               C1_LARGURA
                               C1_ALTURA)
                 #f)
   (check-equal? (lop-validas? (list (posn 0 0)
                                     (posn 1 -1)) ; coluna inválida
                               C1_LARGURA
                               C1_ALTURA)
                 #f)))

(define lop-livres?-tests
  (test-suite
   "lop-livres? tests"
   (check-equal? (lop-livres? C1_LIVRES C1) #t)
   (check-equal? (lop-livres? C1_OCUPADAS C1) #f)
   (check-equal? (lop-livres? (append C1_LIVRES (list (first C1_OCUPADAS))) C1) #f)))

(define fixa-tests
  (test-suite
   "fixa tests"
   (check-equal? (fixa (tetris C1 C1_LARGURA C1_ALTURA TT1 empty TIMEOUT))
                 (tetris C1_FIXA_TT1 C1_LARGURA C1_ALTURA TT1 empty TIMEOUT))))

(define limpa-tests
  (test-suite
   "limpa tests"
   (check-equal? (limpa (tetris C1_FIXA_TT1 C1_LARGURA C1_ALTURA TT1 empty TIMEOUT))
                 (tetris C1_FIXA_TT1_LIMPA C1_LARGURA C1_ALTURA TT1 empty TIMEOUT))))

;; teste para fixar um tetramino no campo alterando a cor
(define fixa-tetramino-no-campo-test
  (test-suite
   "fixa-tetramino-no-campo tests"
   (check-equal? (fixa-tetramino-no-campo (list (posn 2 2) (posn 3 2) (posn 3 3) (posn 4 2)) campoV 0 0 6)
                 campo1)))

;; campo vazio
(define campoV (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 0 0 0 0 0 0 0)   ; 2
                     (list 0 0 0 0 0 0 0)   ; 3
                     (list 0 0 0 0 0 0 0)   ; 4
                     (list 0 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

;; campo com a peca T1 e/ou movido o tetra a direita do campo2
(define campo1 (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 0 0 6 0 0 0 0)   ; 2
                     (list 0 0 6 6 0 0 0)   ; 3
                     (list 0 0 6 0 0 0 0)   ; 4
                     (list 0 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

;; campo com a peca T1 e/ou movido o tetra a esquerda do campo1
(define campo2 (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 0 6 0 0 0 0 0)   ; 2
                     (list 0 6 6 0 0 0 0)   ; 3
                     (list 0 6 0 0 0 0 0)   ; 4
                     (list 0 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

;; campo com a peca T1 e/ou movido o tetra a esquerda do campo2, não podendo mais ser movido a esquerda
(define campo3 (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 6 0 0 0 0 0 0)   ; 2
                     (list 6 6 0 0 0 0 0)   ; 3
                     (list 6 0 0 0 0 0 0)   ; 4
                     (list 0 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

;; campo com a peca T1, não podendo ser movido a esquerda
(define campo4 (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 0 6 0 0 0 0 0)   ; 2
                     (list 0 6 6 0 0 0 0)   ; 3
                     (list 1 6 0 0 0 0 0)   ; 4
                     (list 1 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

;; campo com a peca T1, não podendo ser movido a direita
(define campo5 (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 0 0 0 0 0 6 0)   ; 2
                     (list 0 0 0 0 0 6 6)   ; 3
                     (list 0 0 0 0 0 6 0)   ; 4
                     (list 0 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

;; campo com a peca T1, não podendo ser movido a direita
(define campo6 (list (list 0 0 0 0 0 0 0)   ; 0
                     (list 0 0 0 0 0 0 0)   ; 1
                     (list 0 0 0 0 6 0 0)   ; 2
                     (list 0 0 0 0 6 6 1)   ; 3
                     (list 0 0 0 0 6 0 1)   ; 4
                     (list 0 0 0 0 0 0 0))) ; 5
                     ;     0 1 2 3 4 5 6

(define trata-tecla-esquerda-tests
  (test-suite
   "trata-tecla-esquerda? tests"
   ;; é possivel mover
   (check-equal? (trata-tecla-esquerda (tetris campo1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 1) 6) empty TIMEOUT))
                 (tetris campo2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
   ;; não é possivel mover
   (check-equal? (trata-tecla-esquerda (tetris campo3 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 -1) 6) empty TIMEOUT))
                 (tetris campo3 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 -1) 6) empty TIMEOUT))
   ;; não é possivel mover
   (check-equal? (trata-tecla-esquerda (tetris campo4 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campo4 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
   ;; é possivel mover
   (check-equal? (trata-tecla-esquerda (tetris campoLine C1_LARGURA C1_ALTURA (tetramino I_TIPOS 0 (posn 1 2) I_COR) empty TIMEOUT))
                 (tetris campoLineEsq C1_LARGURA C1_ALTURA (tetramino I_TIPOS 0 (posn 1 1) I_COR) empty TIMEOUT))))

(define trata-tecla-direita-tests
  (test-suite
   "trata-tecla-direita? tests"
   ;; é possivel mover
   (check-equal? (trata-tecla-direita (tetris campo2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campo1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 1) 6) empty TIMEOUT))
   ;; não é possivel mover
   (check-equal? (trata-tecla-direita (tetris campo5 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 5) 6) empty TIMEOUT))
                 (tetris campo5 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 5) 6) empty TIMEOUT))
   ;; não é possivel mover
   (check-equal? (trata-tecla-direita (tetris campo6 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 4) 6) empty TIMEOUT))
                 (tetris campo6 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 4) 6) empty TIMEOUT))
   ;; é possivel mover
   (check-equal? (trata-tecla-direita (tetris campoLineEsq C1_LARGURA C1_ALTURA (tetramino I_TIPOS 0 (posn 1 1) I_COR) empty TIMEOUT))
                 (tetris campoLine C1_LARGURA C1_ALTURA (tetramino I_TIPOS 0 (posn 1 2) I_COR) empty TIMEOUT))))


;; campo com o tetramino T1 com posn(1 0) na cor 6
(define C1_FIXA_TT1_LIMPA_TETRA (list (list 0 0 0 0 0 0 0)   ; 0
                                      (list 0 6 0 0 0 0 0)   ; 1
                                      (list 6 6 6 0 0 0 0)   ; 2
                                      (list 4 6 2 4 6 1 1)   ; 3
                                      (list 3 4 0 0 0 0 0)   ; 4
                                      (list 1 2 4 3 2 5 6))) ; 5
                                      ;     0 1 2 3 4 5 6

;; campo com a peca I0 e/ou movido o tetra a direita do campoLineEsq
(define campoLine (list (list 0 0 0 0 0 0 0)   ; 0
                        (list 0 0 0 0 0 0 0)   ; 1
                        (list 0 0 1 1 1 1 0)   ; 2
                        (list 0 0 0 0 0 0 0)   ; 3
                        (list 0 0 0 0 0 0 0)   ; 4
                        (list 0 0 0 0 0 0 0))) ; 5
                        ;     0 1 2 3 4 5 6

;; campo com a peca I0 e/ou movido o tetra a esquerda do campoLine
(define campoLineEsq (list (list 0 0 0 0 0 0 0)   ; 0
                           (list 0 0 0 0 0 0 0)   ; 1
                           (list 0 1 1 1 1 0 0)   ; 2
                           (list 0 0 0 0 0 0 0)   ; 3
                           (list 0 0 0 0 0 0 0)   ; 4
                           (list 0 0 0 0 0 0 0))) ; 5
                           ;     0 1 2 3 4 5 6

;; teste de rotacao somente
(define rotaciona-tests
  (test-suite
   "rotaciona? tests"
   ;; rotaciona de T0 para T1
   (check-equal? (rotaciona (tetramino T_TIPOS 0 (posn 1 0) 0))
                 (tetramino T_TIPOS 1 (posn 1 0) 0))
   ;; rotaciona de T1 para T2
   (check-equal? (rotaciona (tetramino T_TIPOS 1 (posn 1 0) 0))
                 (tetramino T_TIPOS 2 (posn 1 0) 0))
   ;; rotaciona de T2 para T3
   (check-equal? (rotaciona (tetramino T_TIPOS 2 (posn 1 0) 0))
                 (tetramino T_TIPOS 3 (posn 1 0) 0))
   ;; rotaciona de T3 para T0
   (check-equal? (rotaciona (tetramino T_TIPOS 3 (posn 1 0) 0))
                 (tetramino T_TIPOS 0 (posn 1 0) 0))))

;; campo com o tetra T1
(define campoUp (list (list 0 0 0 0 0 0 0)   ; 0
                      (list 0 0 0 0 0 0 0)   ; 1
                      (list 0 6 0 0 0 0 0)   ; 2
                      (list 0 6 6 0 0 0 0)   ; 3
                      (list 0 6 0 0 0 0 0)   ; 4
                      (list 0 0 0 0 0 0 0))) ; 5
                      ;     0 1 2 3 4 5 6

;; campo com o tetra T1 movido para baixo e não pode ser mais movido para baixo
(define campoDown (list (list 0 0 0 0 0 0 0)   ; 0
                        (list 0 0 0 0 0 0 0)   ; 1
                        (list 0 0 0 0 0 0 0)   ; 2
                        (list 0 6 0 0 0 0 0)   ; 3
                        (list 0 6 6 0 0 0 0)   ; 4
                        (list 0 6 0 0 0 0 0))) ; 5
                        ;     0 1 2 3 4 5 6
;; campo com o tetra T1 movido para baixo e não pode ser mais movido para baixo
(define campoDown2 (list (list 0 0 0 0 0 0 0)   ; 0
                         (list 0 0 0 0 0 0 0)   ; 1
                         (list 0 6 0 0 0 0 0)   ; 2
                         (list 0 6 6 0 0 0 0)   ; 3
                         (list 0 6 0 0 0 0 0)   ; 4
                         (list 0 1 0 0 0 0 0))) ; 5
                         ;     0 1 2 3 4 5 6

(define desloca-tetra-para-baixo-tests
  (test-suite
   "desloca-tetra-para-baixo? tests"
   ;; é possivel
   (check-equal? (desloca-tetra-para-baixo (tetris campoUp C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty TIMEOUT))
   ;; não é possivel
   (check-equal? (desloca-tetra-para-baixo (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty TIMEOUT))
                 (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty TIMEOUT))
   ;; não é possivel
   (check-equal? (desloca-tetra-para-baixo (tetris campoDown2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoDown2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))))


(define trata-tecla-baixo-tests
  (test-suite
   "trata-tecla-baixo? tests"
   ;; é possivel mover
   (check-equal? (trata-tecla-baixo (tetris campoUp C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty 0))
   ;; não é possivel
   (check-equal? (trata-tecla-baixo (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty TIMEOUT))
                 (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty 0))
   ;; não é possivel
   (check-equal? (trata-tecla-baixo (tetris campoDown2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoDown2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty 0))))

(define trata-tecla-tests
  (test-suite
   "trata-tecla? tests"
   ;; é possivel 
   (check-equal? (trata-tecla (tetris campoUp C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT) "down")
                 (tetris campoDown C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 3 0) 6) empty 0))
   ;; é possivel
   (check-equal? (trata-tecla (tetris campo2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT) "right")
                 (tetris campo1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 1) 6) empty TIMEOUT))
   ;; é possivel
   (check-equal? (trata-tecla (tetris campo1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 1) 6) empty TIMEOUT) "left")
                 (tetris campo2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
   ;; é possivel
   (check-equal? (trata-tecla (tetris campoRot0 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 0 (posn 2 0) 6) empty TIMEOUT) "up")
                 (tetris campoRot1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))

))
  
;; campo com tetra T0 sendo a rotacao 0
(define campoRot0 (list (list 0 0 0 0 0 0 0)   ; 0
                        (list 0 0 0 0 0 0 0)   ; 1
                        (list 0 6 0 0 0 0 0)   ; 2
                        (list 6 6 6 0 0 0 0)   ; 3
                        (list 0 0 0 0 0 0 0)   ; 4
                        (list 0 0 0 0 0 0 0))) ; 5
                        ;     0 1 2 3 4 5 6

;; campo com tetra T1 sendo a rotacao 1
(define campoRot1 (list (list 0 0 0 0 0 0 0)   ; 0
                        (list 0 0 0 0 0 0 0)   ; 1
                        (list 0 6 0 0 0 0 0)   ; 2
                        (list 0 6 6 0 0 0 0)   ; 3
                        (list 0 6 0 0 0 0 0)   ; 4
                        (list 0 0 0 0 0 0 0))) ; 5
                        ;     0 1 2 3 4 5 6

;; campo com tetra T2 sendo a rotacao 2
(define campoRot2 (list (list 0 0 0 0 0 0 0)   ; 0
                        (list 0 0 0 0 0 0 0)   ; 1
                        (list 0 0 0 0 0 0 0)   ; 2
                        (list 6 6 6 0 0 0 0)   ; 3
                        (list 0 6 0 0 0 0 0)   ; 4
                        (list 0 0 0 0 0 0 0))) ; 5
                        ;     0 1 2 3 4 5 6

;; campo com tetra T3 sendo a rotacao 3
(define campoRot3 (list (list 0 0 0 0 0 0 0)   ; 0
                        (list 0 0 0 0 0 0 0)   ; 1
                        (list 0 6 0 0 0 0 0)   ; 2
                        (list 6 6 0 0 0 0 0)   ; 3
                        (list 0 6 0 0 0 0 0)   ; 4
                        (list 0 0 0 0 0 0 0))) ; 5
                        ;     0 1 2 3 4 5 6

;; teste de rotacao a partir da tecla up
(define trata-tecla-cima-tests
  (test-suite
   "trata-tecla-cima? tests"
   ;; rotaciona de T0 para T1
   (check-equal? (trata-tecla-cima (tetris campoRot0 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 0 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoRot1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
   ;; rotaciona de T1 para T2
   (check-equal? (trata-tecla-cima (tetris campoRot1 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 1 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoRot2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 2 (posn 2 0) 6) empty TIMEOUT))
   ;; rotaciona de T2 para T3
   (check-equal? (trata-tecla-cima (tetris campoRot2 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 2 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoRot3 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 3 (posn 2 0) 6) empty TIMEOUT))
   ;; rotaciona de T3 para T0
   (check-equal? (trata-tecla-cima (tetris campoRot3 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 3 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoRot0 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 0 (posn 2 0) 6) empty TIMEOUT))))

(define reseta-timeout-tests
  (test-suite
   "reseta-timeout-tests tests"
   (check-equal? (reseta-timeout (tetris campoRot0 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 0 (posn 2 0) 6) empty TIMEOUT))
                 (tetris campoRot0 C1_LARGURA C1_ALTURA (tetramino T_TIPOS 0 (posn 2 0) 6) empty 0))))

(define desenha-tests
  (test-suite
   "desenha-tests tests"
   (check-equal? (desenha (tetris C1 C1_LARGURA C1_ALTURA empty empty TIMEOUT))
                 (above (beside (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black"))
                        (beside (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black"))
                        (beside (rectangle Q-LARGURA Q-ALTURA "solid" "purple")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black"))
                        (beside (rectangle Q-LARGURA Q-ALTURA "solid" "yellow")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "blue")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "yellow")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "purple")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "cyan")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "cyan"))
                        (beside (rectangle Q-LARGURA Q-ALTURA "solid" "orange")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "yellow")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "black"))
                        (beside (rectangle Q-LARGURA Q-ALTURA "solid" "cyan")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "blue")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "yellow")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "orange")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "blue")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "green")
                                (rectangle Q-LARGURA Q-ALTURA "solid" "purple"))))))

;; ---------------------------------------------------------------------

;; Função que executa um grupo de testes.
(define (executar-testes . testes)
  (run-tests (test-suite "Todos os testes" testes))
  (void))

;; Chama a função para executar os testes.

(executar-testes make-linha-tests
                 make-campo-tests
                 centraliza-tests
                 make-tetris-tests
                 tetramino->pos-tests
                 lop-validas?-tests
                 lop-livres?-tests
                 fixa-tests
                 limpa-tests
                 fixa-tetramino-no-campo-test
                 trata-tecla-esquerda-tests
                 trata-tecla-direita-tests
                 rotaciona-tests
                 desloca-tetra-para-baixo
                 trata-tecla-cima-tests
                 reseta-timeout-tests
                 desenha-tests
                 trata-tecla-baixo-tests
                 trata-tecla-tests)